using System;
using Headspring.Training.Core.Model;
using Headspring.Training.Core.Model.StateCommands;
using Headspring.Training.Core.Services;
using Headspring.Training.Core.Services.Impl;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using Rhino.Mocks;

namespace Headspring.Training.UnitTests.Model.StateCommands
{
	[TestFixture]
	public class AssignedToDraftCommandTester
	{
		public class EmailServiceMock : IEmailService
		{
			public string EmailAddress;
			public string Message;

			public void SendMessage(string emailAddress, string message)
			{
				EmailAddress = emailAddress;
				Message = message;
			}
		}

		[Test]
		public void ShouldBeValid()
		{
			var order = new WorkOrder {Status = WorkOrderStatus.Assigned};
			var employee = new Employee();
			order.Assignee = employee;

			var command = new AssignedToDraftCommand(order, employee, null, null);
			Assert.That(command.IsValid(), Is.True);
		}

		[Test]
		public void ShouldNotBeValidInWrongStatus()
		{
			var order = new WorkOrder {Status = WorkOrderStatus.Draft};
			var employee = new Employee();
			order.Assignee = employee;

			var command = new AssignedToDraftCommand(order, employee, null, null);
			Assert.That(command.IsValid(), Is.False);
		}

		[Test]
		public void ShouldNotBeValidWithWrongEmployee()
		{
			var order = new WorkOrder {Status = WorkOrderStatus.Assigned};
			var employee = new Employee();
			order.Creator = employee;

			var command = new AssignedToDraftCommand(order, employee, null, null);
			Assert.That(command.IsValid(), Is.False);
		}

		[Test]
		public void ShouldSendEmailIfAssigneeReportsToCreator()
		{
			var order = new WorkOrder {Number = "123", Status = WorkOrderStatus.Assigned};
			var employee = new Employee();
			var manager = MockRepository.GenerateStub<Manager>();
			manager.Stub(manager1 => manager1.GetRejectEmail(DayOfWeek.Friday))
				.Return("e@mail.com");

			employee.Manager = manager;

			order.Assignee = employee;
			order.Creator = manager;

			var emailService = new EmailServiceMock();
			var commandVisitor = MockRepository.GenerateMock<IStateCommandVisitor>();
			commandVisitor.Expect(visitor => visitor.SaveWorkOrder(order));
			commandVisitor.Expect(
				visitor => visitor.SendMessage("You have rejected work order 123"));
			commandVisitor.Expect(visitor => visitor.EditWorkOrder(order));

			var command = new AssignedToDraftCommand(order, employee, emailService, new StubbedCalendar(new DateTime(2008, 7, 18)));
			command.Execute(commandVisitor);

			commandVisitor.VerifyAllExpectations();

			Assert.That(emailService.EmailAddress, Is.EqualTo("e@mail.com"));
			Assert.That(emailService.Message, Is.EqualTo("Not gonna do it."));
		}

		[Test]
		public void ShouldShowCorrectVerb()
		{
			var command = new AssignedToDraftCommand(null, null, null, null);

			Assert.AreEqual("Reject", command.TransitionVerbPresentTense);
			Assert.AreEqual("Rejected", command.TransitionVerbPastTense);
		}

		[Test]
		public void ShouldTransitionStateProperlyWithNoEmail()
		{
			var order = new WorkOrder {Number = "123", Status = WorkOrderStatus.Assigned};
			var employee = new Employee();
			order.Assignee = employee;
			order.Creator = employee;

			var commandVisitor = MockRepository.GenerateMock<IStateCommandVisitor>();
			commandVisitor.Expect(visitor => visitor.SaveWorkOrder(order));
			commandVisitor.Expect(
				visitor => visitor.SendMessage("You have rejected work order 123"));
			commandVisitor.Expect(visitor => visitor.EditWorkOrder(order));

			var command = new AssignedToDraftCommand(order, employee, null, new StubbedCalendar(DateTime.Now));
			command.Execute(commandVisitor);

			commandVisitor.VerifyAllExpectations();
			Assert.That(order.Status, Is.EqualTo(WorkOrderStatus.Draft));
		}
	}
}